package com.sukaiyi.giteeideaplugin.mainwindow;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.treeStructure.Tree;
import com.sukaiyi.giteeideaplugin.cellrenderer.CodeSegmentTreeCellRenderer;
import com.sukaiyi.giteeideaplugin.component.LoadingContainer;
import com.sukaiyi.giteeideaplugin.model.CodeSegmentNode;
import com.sukaiyi.giteeideaplugin.search.codesegments.CodeSegmentData;
import com.sukaiyi.giteeideaplugin.utils.NotificationUtils;
import com.sukaiyi.giteejavaapi.common.Gitee;
import com.sukaiyi.giteejavaapi.common.Params;
import com.sukaiyi.giteejavaapi.http.model.HttpResponse;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

/**
 * @author sukaiyi
 * @date 2020/07/16
 */
public class CodeSegmentWindow implements LoadingContainer.Loadable {
    private JPanel content;
    private JBScrollPane scrollPane;
    private Tree codeSegmentsTree;

    public CodeSegmentWindow(ToolWindow toolWindow) {
        DefaultActionGroup actionGroup = createActionGroup();
        ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar("Group Toolbar", actionGroup, true);
        content.add(actionToolbar.getComponent(), BorderLayout.NORTH);

        refresh();
    }

    private void refresh() {
        loading();
        CompletableFuture.supplyAsync(() -> CodeSegmentData.getInstance().getRoot())
                .thenApply(this::toTreeNode) // 转换成 TreeNode
                .thenAccept(this::updateCodeSegmentTree)
                .thenApply(args -> {
                    Params params = Params.create()
                            .set("since", "2000-01-01T17:30:08+08:00")
                            .set("page", "1")
                            .set("per_page", "100");
                    return Gitee.getInstance().invoke("getV5Gists", params).join();
                })
                .thenApply(HttpResponse::asJSONArray) // 结果转换成数据
                .thenApply(this::parseCodeSegmentTree) // 解析成 CodeSegmentNode
                .thenApply(this::toTreeNode) // 转换成 TreeNode
                .thenAccept(this::updateCodeSegmentTree)
                .whenComplete((ret, ex) -> {
                    loaded();
                    if (ex != null) {
                        NotificationUtils.notify(ex.getMessage());
                    }
                });
    }

    private CodeSegmentNode parseCodeSegmentTree(JSONArray arr) {
        Function<JSONObject, java.util.List<CodeSegmentNode>> handleFiles = obj -> {
            JSONObject filesObj = obj.getJSONObject("files");
            java.util.List<CodeSegmentNode> children = new ArrayList<>();
            for (String name : filesObj.keySet()) {
                JSONObject fileObj = filesObj.getJSONObject(name);
                CodeSegmentNode node = new CodeSegmentNode();
                node.setId(obj.getStr("id"));
                node.setName(name);
                node.setNodeType("file");
                node.setType(fileObj.getStr("type"));
                node.setSize(fileObj.getLong("size"));
                node.setRawUrl(fileObj.getStr("raw_url"));
                node.setTruncated(fileObj.getBool("truncated"));
                node.setContent(fileObj.getStr("content"));
                children.add(node);
            }
            return children;
        };

        CodeSegmentNode root = new CodeSegmentNode();
        root.setNodeType("group");
        root.setDescription("Code Segments");
        java.util.List<CodeSegmentNode> children = new ArrayList<>();
        for (int i = 0; i < arr.size(); i++) {
            JSONObject obj = arr.getJSONObject(i);
            CodeSegmentNode node = new CodeSegmentNode();
            node.setId(obj.getStr("id"));
            node.setDescription(obj.getStr("description"));
            node.setTruncated(obj.getBool("truncated"));
            node.setNodeType("group");
            node.setChildren(handleFiles.apply(obj));
            children.add(node);
        }
        root.setChildren(children);
        CodeSegmentData.getInstance().setRoot(root);
        return root;
    }

    private MutableTreeNode toTreeNode(CodeSegmentNode codeNode) {
        if (codeNode == null) {
            return null;
        }
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(codeNode);
        List<CodeSegmentNode> children = codeNode.getChildren();
        if (children != null && children.size() > 0) {
            for (CodeSegmentNode child : children) {
                node.add(toTreeNode(child));
            }
        }
        return node;
    }

    private void updateCodeSegmentTree(TreeNode treeNode) {
        SwingUtilities.invokeLater(() -> codeSegmentsTree.setModel(new DefaultTreeModel(treeNode)));
    }

    @Override
    public JComponent getContent() {
        return content;
    }

    private void createUIComponents() {
        codeSegmentsTree = new Tree();
        codeSegmentsTree.setCellRenderer(new CodeSegmentTreeCellRenderer());
        scrollPane = new JBScrollPane(codeSegmentsTree);

        codeSegmentsTree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                if (e.getClickCount() != 2) {
                    return;
                }
                DefaultMutableTreeNode[] treeNodes = codeSegmentsTree.getSelectedNodes(DefaultMutableTreeNode.class, null);
                if (treeNodes.length <= 0) {
                    return;
                }
                DefaultMutableTreeNode treeNode = treeNodes[0];
                CodeSegmentNode node = (CodeSegmentNode) treeNode.getUserObject();
                if (!Objects.equals(node.getNodeType(), "file")) {
                    return;
                }
                new CodeSegmentWindowDialogWrapper(node).showAndGet();
            }
        });
    }

    private DefaultActionGroup createActionGroup() {
        DefaultActionGroup actionGroup = new DefaultActionGroup();
        // 刷新页面
        actionGroup.add(new AnAction(AllIcons.Actions.Refresh) {
            @Override
            public void actionPerformed(@NotNull AnActionEvent event) {
                refresh();
            }
        });
        // 添加
        actionGroup.add(new AnAction(AllIcons.Welcome.CreateNewProject) {
            @Override
            public void actionPerformed(@NotNull AnActionEvent e) {

            }
        });
        // 删除仓库
        actionGroup.add(new AnAction(AllIcons.General.Remove) {
            @Override
            public void actionPerformed(@NotNull AnActionEvent e) {
            }
        });
        // 浏览器中打开
        actionGroup.add(new AnAction(AllIcons.General.Web) {
            @Override
            public void actionPerformed(@NotNull AnActionEvent e) {
            }
        });
        actionGroup.addSeparator();
        actionGroup.add(new AnAction(AllIcons.Actions.Help) {
            @Override
            public void actionPerformed(@NotNull AnActionEvent e) {
            }
        });
        return actionGroup;
    }



}
